Introduction

This notebook…

Dependencies

This notebook requires…

# tidyverse packages
library(dplyr)       # data wrangling
library(readr)       # read/write tabular data
library(stringr)     # work with strings
library(tidyr)       # data wrangling
# spatial packages
library(janitor)     # data wrangling
library(sf)          # spatial data tools
library(mapview)     # projections
library(tigris)      # census data wrangling 
# other packages
library(here)        # file path management
library(naniar)      # missing data
library(ggplot2)
library(viridis)      # palettes
library(leaflet)
library(tidycensus) 
library(sp)
library(ggplot2)   
library(RColorBrewer)  # color palettes
library(viridis)       # color palettes

Load Data 2015

loading asthma data from MoPhim data base asthma is for 2015

asthma_15 <- read_csv(here("data","raw", "asthma", "asthma2015.csv"))
Missing column names filled in: 'X3' [3]Parsed with column specification:
cols(
  `Title:` = col_character(),
  `Missouri EPHT Asthma` = col_character(),
  X3 = col_logical()
)
1031 parsing failures.
row col  expected    actual                                                                                                                file
  1  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2015.csv'
  2  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2015.csv'
  3  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2015.csv'
  4  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2015.csv'
  5  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2015.csv'
... ... ......... ......... ...................................................................................................................
See problems(...) for more details.

Getting rid of first three rows bc they are pointless text.

asthma_15 %>%
  slice(4:1029) -> asthma_15

Getting rid of third col with no data. aslo renaming cols to ‘count’ and ‘zip’

asthma_15 %>%
  select(-X3) %>%
  rename(count = `Missouri EPHT Asthma`) %>%
  rename(zip = `Title:`)-> asthma_15

Changing X to NA, making the count variable numeric

mutate(asthma_15, count = ifelse(count == "x", NA, count)) -> asthma_15
mutate(asthma_15, count = as.numeric(count)) -> asthma_15

`

loading Mo zip codes

moZip <- zctas(state = "Missouri", year = 2010,
               cb = FALSE, class ="sf")
Using FIPS code '29' for state 'Missouri'
ZCTAs can take several minutes to download.  To cache the data and avoid re-downloading in future R sessions, set `options(tigris_use_cache = TRUE)`

Changing object to SF

st_as_sf(moZip) -> moZip

cleaning names, selecting just cols for zip and geometry, changing col name to zip

moZip %>%
  clean_names() %>%
  select(zcta5ce10, geometry) %>%
  rename(zip = `zcta5ce10`)-> moZip

Load Data 2014

loading data for asthma 2014

asthma_14<- read_csv(here("data","raw", "asthma", "asthma2014.csv"))
Missing column names filled in: 'X3' [3]Parsed with column specification:
cols(
  `Title:` = col_character(),
  `Missouri EPHT Asthma` = col_character(),
  X3 = col_logical()
)
1031 parsing failures.
row col  expected    actual                                                                                                                file
  1  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2014.csv'
  2  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2014.csv'
  3  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2014.csv'
  4  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2014.csv'
  5  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2014.csv'
... ... ......... ......... ...................................................................................................................
See problems(...) for more details.

getting rid of first three rows bc they have nothing in them

asthma_14 %>%
  slice(4:1029) -> asthma_14

getting rid of empty third col, renaming remaning cols

asthma_14 %>%
  select(-X3) %>%
  rename(count = `Missouri EPHT Asthma`) %>%
  rename(zip = `Title:`) -> asthma_14

changing X to NA, changing to numeric

mutate(asthma_14, count = ifelse(count == "x", NA, count)) -> asthma_14
mutate(asthma_14, count = as.numeric(count)) -> asthma_14

left join to asthma_cleaned by zip. Now table has data for both 2014 and 2015

left_join(asthma_15, asthma_14, by = "zip") -> asthma_full

Load Data 2013

loading asthma data for 2013

asthma_13 <- read_csv(here("data","raw", "asthma", "asthma2013.csv")) 
Missing column names filled in: 'X3' [3]Parsed with column specification:
cols(
  `Title:` = col_character(),
  `Missouri EPHT Asthma` = col_character(),
  X3 = col_logical()
)
1031 parsing failures.
row col  expected    actual                                                                                                                file
  1  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2013.csv'
  2  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2013.csv'
  3  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2013.csv'
  4  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2013.csv'
  5  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2013.csv'
... ... ......... ......... ...................................................................................................................
See problems(...) for more details.

Getting rid of first 4 rows bc they have no data

asthma_13 %>%
  slice(4:1029) -> asthma_13

getting rid of third col, renaming other cols

asthma_13 %>%
  select(-X3) %>%
  rename(count_13 = `Missouri EPHT Asthma`) %>%
  rename(zip = `Title:`) -> asthma_13

changing X to NA, changing count to numeric

mutate(asthma_13, count_13 = ifelse(count_13 == "x", NA, count_13)) -> asthma_13
mutate(asthma_13, count_13 = as.numeric(count_13)) -> asthma_13

left joing to joined_14_15, so table now has data for years 2013, 2014, and 2015

left_join(asthma_full, asthma_13, by = "zip") -> asthma_full

Load Data 2012

loading data for 2012

asthma_12 <- read_csv(here("data","raw", "asthma", "asthma2012.csv")) 
Missing column names filled in: 'X3' [3]Parsed with column specification:
cols(
  `Title:` = col_character(),
  `Missouri EPHT Asthma` = col_character(),
  X3 = col_logical()
)
1031 parsing failures.
row col  expected    actual                                                                                                                file
  1  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2012.csv'
  2  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2012.csv'
  3  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2012.csv'
  4  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2012.csv'
  5  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2012.csv'
... ... ......... ......... ...................................................................................................................
See problems(...) for more details.

getting rid of empty cols

asthma_12 %>%
  slice(4:1029) -> asthma_12

cleaning data

asthma_12 %>%
  select(-X3) %>%
  rename(count_12 = `Missouri EPHT Asthma`) %>%
  rename(zip = `Title:`) -> asthma_12

changing X to NA and changing count to numeric

mutate(asthma_12, count_12 = ifelse(count_12 == "x", NA, count_12)) -> asthma_12
mutate(asthma_12, count_12 = as.numeric(count_12)) -> asthma_12

left joing to joined_13_14_15 by zip. Table now has data for 2012 through 2015

left_join(asthma_full, asthma_12, by = "zip") -> asthma_full

Load Data 2011

loading data for 2011

asthma_11 <- read_csv(here("data","raw", "asthma", "asthma2011.csv")) 
Missing column names filled in: 'X3' [3]Parsed with column specification:
cols(
  `Title:` = col_character(),
  `Missouri EPHT Asthma` = col_character(),
  X3 = col_logical()
)
1031 parsing failures.
row col  expected    actual                                                                                                                file
  1  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2011.csv'
  2  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2011.csv'
  3  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2011.csv'
  4  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2011.csv'
  5  -- 3 columns 4 columns '/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/raw/asthma/asthma2011.csv'
... ... ......... ......... ...................................................................................................................
See problems(...) for more details.

getting rid of empty cols

asthma_11 %>%
  slice(4:1029) -> asthma_11

cleaning data

asthma_11 %>%
  select(-X3) %>%
  rename(count_11 = `Missouri EPHT Asthma`) %>%
  rename(zip = `Title:`) -> asthma_11

changing X to NA, and changing count to be numeric

mutate(asthma_11, count_11 = ifelse(count_11 == "x", NA, count_11)) -> asthma_11
mutate(asthma_11, count_11 = as.numeric(count_11)) -> asthma_11

Joining data for years 2011-2015

joining to joined_12_15 for years 2011-2015

left_join(asthma_full, asthma_11, by = "zip") -> asthma_full

joining data with geometry by zip

asthma_full <- left_join(moZip, asthma_full, by = "zip")
asthma_full %>%
rename(
  count_14 = count.y,
  count_15 = count.x
) -> asthma_full

Zip codes for St Louis metro area

filtering for Zip codes in St Louis Metro Area, first filter gets range, Exclude gets rid of zip codes in that range that aren’t included in the metro area.

asthma_full %>%
  filter(zip >= (63005))%>%
  filter(zip <= (63390)) -> asthma_full
exclude <- c(63091, 63155, 63333, 63334, 63336, 63339, 63344, 63345, 63350, 63351, 63352, 63353, 63359, 63359, 63361, 63363, 63382, 63388, 63384, 63036, 63087, 63330)
asthma_full %>%
filter(as.character(zip) %in% exclude == FALSE) -> asthma_full

changing NA’s to 0s

asthma_full%>%
  mutate(count_11 = ifelse(is.na(count_11) == TRUE, 0, count_11)) %>%
  mutate(count_12 = ifelse(is.na(count_12) == TRUE, 0, count_12)) %>%
  mutate(count_13 = ifelse(is.na(count_13) == TRUE, 0, count_13)) %>%
  mutate(count_14 = ifelse(is.na(count_14) == TRUE, 0, count_14)) %>%
  mutate(count_15 = ifelse(is.na(count_15) == TRUE, 0, count_15))-> asthma_full

Creating Count variable

Creating count for all 5 years

asthma_full %>%
  group_by(zip) %>%
  mutate(total_count = sum(count_15, count_14, count_13, count_12, count_11)) %>%
  select(zip, total_count, geometry) -> asthma_full

rowwise() %>% getting census data to get population for zip code tracts. using 5 year estimates from 2015

#acs <- load_variables(year = 2015, dataset = "acs5", cache = TRUE)
pop <- get_acs(geography = "zip code tabulation area", year = 2015, variables = "B01003_001", survey = "acs5")
Getting data from the 2011-2015 5-year ACS

filtering for zip codes in st. louis metro area

pop %>%
  filter(GEOID >= (63005))%>%
  filter(GEOID <= (63390)) ->pop
pop %>%
  filter(as.character(GEOID) %in% exclude == FALSE)%>%
  rename(zip = GEOID,
         pop = estimate) %>%
  select(zip, pop) -> pop

left join pop_metro to asthma_count_total, making variable for count

left_join(asthma_full, pop, by = "zip") %>%
  mutate(asthma_rate = (total_count/pop)*1000) %>%
 select(zip, asthma_rate, geometry) -> asthma_full
mapview(asthma_full)

creating ggplot map

ggplot() +
    geom_sf(data = asthma_full, mapping = aes(fill = asthma_rate)) +
  scale_fill_distiller(palette = "Greens", trans ="reverse")

saving shapefile file for Asthma data for years 2011-2015

dir.create(here("data","clean", "asthma", "asthma_full"))
'/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/asthma/asthma_full' already exists
st_write(asthma_full, dsn = here("data", "clean", "asthma", "asthma_full", "asthma_full.shp"), delete_dsn = TRUE)
Field names abbreviated for ESRI Shapefile driver
Deleting source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/asthma/asthma_full/asthma_full.shp' using driver `ESRI Shapefile'
Writing layer `asthma_full' to data source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/asthma/asthma_full/asthma_full.shp' using driver `ESRI Shapefile'
features:       127
fields:         2
geometry type:  Multi Polygon

loading Data for % African American

loading data for year 2015 (five year estimate)

aa <- get_acs(geography = "zip code tabulation area", year = 2015, variables = "B02009_001", survey = "acs5")
Getting data from the 2011-2015 5-year ACS
aa %>%
rename(zip = GEOID) -> aa

Joining with pop data

aa <- left_join(aa, pop, by = "zip") 

normalizing by pop

aa %>%
mutate(percent_aa = estimate/pop) %>%
 rename(african_american = estimate) -> aa

join with asthma data

aa <- left_join(asthma_full, aa, by = "zip")
aa %>%
  select(zip, asthma_rate, african_american, pop, percent_aa) -> aa

saving shapefile file for % african american

dir.create(here("data","clean", "demo", "precent_aa"))
st_write(aa, dsn = here("data", "clean", "demo", "precent_aa", "precent_aa.shp"), delete_dsn = TRUE)
Field names abbreviated for ESRI Shapefile driverGDAL Error 1: /Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/precent_aa/precent_aa.shp does not appear to be a file or directory.
Deleting source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/precent_aa/precent_aa.shp' failed
Writing layer `precent_aa' to data source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/precent_aa/precent_aa.shp' using driver `ESRI Shapefile'
features:       127
fields:         5
geometry type:  Multi Polygon

loading data for median income

loading five year estimate for 2015

median_income <- get_acs(geography = "zip code tabulation area", year = 2015, variables = "B06011_001", survey = "acs5")
Getting data from the 2011-2015 5-year ACS
median_income %>%
rename(zip = GEOID) -> median_income

join with pop data

median_income <- left_join(median_income, pop, by = "zip") 

normalize by pop

median_income%>%
mutate(income_precent = estimate/pop) %>%
rename(median_income = estimate) -> median_income

join with asthma data

median_income <- left_join(asthma_full, median_income, by = "zip")
median_income %>%
  select(zip, asthma_rate, median_income, pop, income_precent) -> median_income

saving as shapefile

dir.create(here("data","clean", "demo", "med_income"))
st_write(median_income, dsn = here("data", "clean", "demo", "med_income", "med_income.shp"), delete_dsn = TRUE)
Field names abbreviated for ESRI Shapefile driverGDAL Error 1: /Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/med_income/med_income.shp does not appear to be a file or directory.
Deleting source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/med_income/med_income.shp' failed
Writing layer `med_income' to data source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/med_income/med_income.shp' using driver `ESRI Shapefile'
features:       127
fields:         5
geometry type:  Multi Polygon

loading data for median home value

loading 5 year estimate from 2015

home_value <- get_acs(geography = "zip code tabulation area", year = 2015, variables = "B25077_001", survey = "acs5")
Getting data from the 2011-2015 5-year ACS
home_value %>%
rename(zip = GEOID) -> home_value

joining with pop data

home_value <- left_join(home_value, pop, by = "zip") 

normalizing by pop

home_value%>%
mutate(value_percent = estimate/pop) %>%
rename(home_value = estimate) -> home_value

joining with asthma data

home_value <- left_join(asthma_full, home_value, by = "zip")
home_value %>%
  select(zip, asthma_rate, home_value, pop, value_percent) -> home_value

saving as shapefile

dir.create(here("data","clean", "demo", "home_value"))
st_write(home_value, dsn = here("data", "clean", "demo", "home_value", "home_value.shp"), delete_dsn = TRUE)
Field names abbreviated for ESRI Shapefile driverGDAL Error 1: /Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/home_value/home_value.shp does not appear to be a file or directory.
Deleting source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/home_value/home_value.shp' failed
Writing layer `home_value' to data source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/home_value/home_value.shp' using driver `ESRI Shapefile'
features:       127
fields:         5
geometry type:  Multi Polygon

loading data for medicaide

loading five year estimate from 2015

medicaid <- get_acs(geography = "zip code tabulation area", year = 2015, variables = "B992707_001", survey = "acs5")
Getting data from the 2011-2015 5-year ACS
medicaid %>%
rename(zip = GEOID) -> medicaid

joining with pop

medicaid <- left_join(medicaid, pop, by = "zip") 

normalizing by pop

medicaid %>%
mutate(percent_medicaid = estimate/pop) %>%
rename(medicaid = estimate) -> medicaid

joining with asthma data

medicaid <- left_join(asthma_full, medicaid, by = "zip")
medicaid %>%
  select(zip, asthma_rate, medicaid, pop, percent_medicaid) -> medicaid

saving as shapefile

dir.create(here("data","clean", "demo", "medicaid"))
st_write(medicaid, dsn = here("data", "clean", "demo", "medicaid", "medicaid.shp"), delete_dsn = TRUE)
Field names abbreviated for ESRI Shapefile driverGDAL Error 1: /Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/medicaid/medicaid.shp does not appear to be a file or directory.
Deleting source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/medicaid/medicaid.shp' failed
Writing layer `medicaid' to data source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/medicaid/medicaid.shp' using driver `ESRI Shapefile'
features:       127
fields:         5
geometry type:  Multi Polygon

loading data for % under poverty line

loading five year estimates for 2015

poverty <- get_acs(geography = "zip code tabulation area", year = 2015, variables = "B17001_002", survey = "acs5")
Getting data from the 2011-2015 5-year ACS

loading poverty total

poverty_total <- get_acs(geography = "zip code tabulation area", year = 2015, variables = "B17001_001", survey = "acs5")
Getting data from the 2011-2015 5-year ACS
poverty %>%
  select(GEOID, estimate) -> poverty
poverty <- left_join(poverty, poverty_total, by = "GEOID") 

normalizing by povery total

poverty %>%
  mutate(poverty_percent = estimate.x/estimate.y) %>%
  rename(zip = GEOID,
         poverty = estimate.x,
         pov_total = estimate.y) -> poverty
Error in mutate_impl(.data, dots) : 
  Evaluation error: object 'estimate.x' not found.

joining with asthma data

poverty <- left_join(asthma_full, poverty, by = "zip")
poverty %>%
  select(zip, asthma_rate, poverty, pov_total, poverty_percent) -> poverty
dir.create(here("data","clean", "demo", "poverty"))
st_write(poverty, dsn = here("data", "clean", "demo", "poverty", "poverty.shp"), delete_dsn = TRUE)
Field names abbreviated for ESRI Shapefile driverGDAL Error 1: /Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/poverty/poverty.shp does not appear to be a file or directory.
Deleting source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/poverty/poverty.shp' failed
Writing layer `poverty' to data source `/Users/avagagner/Desktop/Courses/Spring2019/SOC4650/GitHub/redliningAsthma-Zipcode/data/clean/demo/poverty/poverty.shp' using driver `ESRI Shapefile'
features:       127
fields:         5
geometry type:  Multi Polygon
LS0tCnRpdGxlOiAiQ2xlYW5pbmcgQXN0aG1hIERhdGEgIgphdXRob3I6ICJBdmEiCmRhdGU6ICcoYHIgZm9ybWF0KFN5cy50aW1lKCksICIlQiAlZCwgJVkiKWApJwpvdXRwdXQ6IAogIGdpdGh1Yl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQgCi0tLQoKIyMgSW50cm9kdWN0aW9uClRoaXMgbm90ZWJvb2suLi4KCiMjIERlcGVuZGVuY2llcwpUaGlzIG5vdGVib29rIHJlcXVpcmVzLi4uCgpgYGB7ciBsb2FkLXBhY2thZ2VzfQojIHRpZHl2ZXJzZSBwYWNrYWdlcwpsaWJyYXJ5KGRwbHlyKSAgICAgICAjIGRhdGEgd3JhbmdsaW5nCmxpYnJhcnkocmVhZHIpICAgICAgICMgcmVhZC93cml0ZSB0YWJ1bGFyIGRhdGEKbGlicmFyeShzdHJpbmdyKSAgICAgIyB3b3JrIHdpdGggc3RyaW5ncwpsaWJyYXJ5KHRpZHlyKSAgICAgICAjIGRhdGEgd3JhbmdsaW5nCiMgc3BhdGlhbCBwYWNrYWdlcwpsaWJyYXJ5KGphbml0b3IpICAgICAjIGRhdGEgd3JhbmdsaW5nCmxpYnJhcnkoc2YpICAgICAgICAgICMgc3BhdGlhbCBkYXRhIHRvb2xzCmxpYnJhcnkobWFwdmlldykgICAgICMgcHJvamVjdGlvbnMKbGlicmFyeSh0aWdyaXMpICAgICAgIyBjZW5zdXMgZGF0YSB3cmFuZ2xpbmcgCiMgb3RoZXIgcGFja2FnZXMKbGlicmFyeShoZXJlKSAgICAgICAgIyBmaWxlIHBhdGggbWFuYWdlbWVudApsaWJyYXJ5KG5hbmlhcikgICAgICAjIG1pc3NpbmcgZGF0YQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodmlyaWRpcykgICAgICAjIHBhbGV0dGVzCmxpYnJhcnkobGVhZmxldCkKbGlicmFyeSh0aWR5Y2Vuc3VzKSAKbGlicmFyeShzcCkKbGlicmFyeShnZ3Bsb3QyKSAgIApsaWJyYXJ5KFJDb2xvckJyZXdlcikgICMgY29sb3IgcGFsZXR0ZXMKbGlicmFyeSh2aXJpZGlzKSAgICAgICAjIGNvbG9yIHBhbGV0dGVzCgoKYGBgCgoKCiMjIExvYWQgRGF0YSAyMDE1CmxvYWRpbmcgYXN0aG1hIGRhdGEgZnJvbSBNb1BoaW0gZGF0YSBiYXNlCmFzdGhtYSBpcyBmb3IgMjAxNQoKYGBge3IgbG9hZC1kYXRhfQphc3RobWFfMTUgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YSIsInJhdyIsICJhc3RobWEiLCAiYXN0aG1hMjAxNS5jc3YiKSkKYGBgCgoKR2V0dGluZyByaWQgb2YgZmlyc3QgdGhyZWUgcm93cyBiYyB0aGV5IGFyZSBwb2ludGxlc3MgdGV4dC4gCmBgYHtyIHAxLXExfQphc3RobWFfMTUgJT4lCiAgc2xpY2UoNDoxMDI5KSAtPiBhc3RobWFfMTUKYGBgCgpHZXR0aW5nIHJpZCBvZiB0aGlyZCBjb2wgd2l0aCBubyBkYXRhLiBhc2xvIHJlbmFtaW5nIGNvbHMgdG8gJ2NvdW50JyBhbmQgJ3ppcCcKYGBge3J9CmFzdGhtYV8xNSAlPiUKICBzZWxlY3QoLVgzKSAlPiUKICByZW5hbWUoY291bnQgPSBgTWlzc291cmkgRVBIVCBBc3RobWFgKSAlPiUKICByZW5hbWUoemlwID0gYFRpdGxlOmApLT4gYXN0aG1hXzE1CmBgYAoKQ2hhbmdpbmcgWCB0byBOQSwgbWFraW5nIHRoZSBjb3VudCB2YXJpYWJsZSBudW1lcmljCmBgYHtyfQptdXRhdGUoYXN0aG1hXzE1LCBjb3VudCA9IGlmZWxzZShjb3VudCA9PSAieCIsIE5BLCBjb3VudCkpIC0+IGFzdGhtYV8xNQpgYGAKYGBge3J9Cm11dGF0ZShhc3RobWFfMTUsIGNvdW50ID0gYXMubnVtZXJpYyhjb3VudCkpIC0+IGFzdGhtYV8xNQpgYGAKYAoKbG9hZGluZyBNbyB6aXAgY29kZXMgCmBgYHtyfQptb1ppcCA8LSB6Y3RhcyhzdGF0ZSA9ICJNaXNzb3VyaSIsIHllYXIgPSAyMDEwLAogICAgICAgICAgICAgICBjYiA9IEZBTFNFLCBjbGFzcyA9InNmIikKYGBgCgpDaGFuZ2luZyBvYmplY3QgdG8gU0YKYGBge3J9CnN0X2FzX3NmKG1vWmlwKSAtPiBtb1ppcApgYGAKCmNsZWFuaW5nIG5hbWVzLCBzZWxlY3RpbmcganVzdCBjb2xzIGZvciB6aXAgYW5kIGdlb21ldHJ5LCBjaGFuZ2luZyBjb2wgbmFtZSB0byB6aXAKYGBge3J9Cm1vWmlwICU+JQogIGNsZWFuX25hbWVzKCkgJT4lCiAgc2VsZWN0KHpjdGE1Y2UxMCwgZ2VvbWV0cnkpICU+JQogIHJlbmFtZSh6aXAgPSBgemN0YTVjZTEwYCktPiBtb1ppcApgYGAKCiMjIExvYWQgRGF0YSAyMDE0CmxvYWRpbmcgZGF0YSBmb3IgYXN0aG1hIDIwMTQKYGBge3J9CmFzdGhtYV8xNDwtIHJlYWRfY3N2KGhlcmUoImRhdGEiLCJyYXciLCAiYXN0aG1hIiwgImFzdGhtYTIwMTQuY3N2IikpCmBgYAoKZ2V0dGluZyByaWQgb2YgZmlyc3QgdGhyZWUgcm93cyBiYyB0aGV5IGhhdmUgbm90aGluZyBpbiB0aGVtIApgYGB7cn0KYXN0aG1hXzE0ICU+JQogIHNsaWNlKDQ6MTAyOSkgLT4gYXN0aG1hXzE0CmBgYAoKZ2V0dGluZyByaWQgb2YgZW1wdHkgdGhpcmQgY29sLCByZW5hbWluZyByZW1hbmluZyBjb2xzCmBgYHtyfQphc3RobWFfMTQgJT4lCiAgc2VsZWN0KC1YMykgJT4lCiAgcmVuYW1lKGNvdW50ID0gYE1pc3NvdXJpIEVQSFQgQXN0aG1hYCkgJT4lCiAgcmVuYW1lKHppcCA9IGBUaXRsZTpgKSAtPiBhc3RobWFfMTQKYGBgCgpjaGFuZ2luZyBYIHRvIE5BLCBjaGFuZ2luZyB0byBudW1lcmljCmBgYHtyfQptdXRhdGUoYXN0aG1hXzE0LCBjb3VudCA9IGlmZWxzZShjb3VudCA9PSAieCIsIE5BLCBjb3VudCkpIC0+IGFzdGhtYV8xNApgYGAKCmBgYHtyfQptdXRhdGUoYXN0aG1hXzE0LCBjb3VudCA9IGFzLm51bWVyaWMoY291bnQpKSAtPiBhc3RobWFfMTQKYGBgCmxlZnQgam9pbiB0byBhc3RobWFfY2xlYW5lZCBieSB6aXAuIE5vdyB0YWJsZSBoYXMgZGF0YSBmb3IgYm90aCAyMDE0IGFuZCAyMDE1IApgYGB7cn0KbGVmdF9qb2luKGFzdGhtYV8xNSwgYXN0aG1hXzE0LCBieSA9ICJ6aXAiKSAtPiBhc3RobWFfZnVsbApgYGAKCiMjIExvYWQgRGF0YSAyMDEzCmxvYWRpbmcgYXN0aG1hIGRhdGEgZm9yIDIwMTMgCmBgYHtyfQphc3RobWFfMTMgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YSIsInJhdyIsICJhc3RobWEiLCAiYXN0aG1hMjAxMy5jc3YiKSkgCmBgYApHZXR0aW5nIHJpZCBvZiBmaXJzdCA0IHJvd3MgYmMgdGhleSBoYXZlIG5vIGRhdGEgCmBgYHtyfQphc3RobWFfMTMgJT4lCiAgc2xpY2UoNDoxMDI5KSAtPiBhc3RobWFfMTMKYGBgCgpnZXR0aW5nIHJpZCBvZiB0aGlyZCBjb2wsIHJlbmFtaW5nIG90aGVyIGNvbHMKYGBge3J9CmFzdGhtYV8xMyAlPiUKICBzZWxlY3QoLVgzKSAlPiUKICByZW5hbWUoY291bnRfMTMgPSBgTWlzc291cmkgRVBIVCBBc3RobWFgKSAlPiUKICByZW5hbWUoemlwID0gYFRpdGxlOmApIC0+IGFzdGhtYV8xMwpgYGAKCmNoYW5naW5nIFggdG8gTkEsIGNoYW5naW5nIGNvdW50IHRvIG51bWVyaWMgCmBgYHtyfQptdXRhdGUoYXN0aG1hXzEzLCBjb3VudF8xMyA9IGlmZWxzZShjb3VudF8xMyA9PSAieCIsIE5BLCBjb3VudF8xMykpIC0+IGFzdGhtYV8xMwpgYGAKYGBge3J9Cm11dGF0ZShhc3RobWFfMTMsIGNvdW50XzEzID0gYXMubnVtZXJpYyhjb3VudF8xMykpIC0+IGFzdGhtYV8xMwpgYGAKbGVmdCBqb2luZyB0byBqb2luZWRfMTRfMTUsIHNvIHRhYmxlIG5vdyBoYXMgZGF0YSBmb3IgeWVhcnMgMjAxMywgMjAxNCwgYW5kIDIwMTUgCmBgYHtyfQpsZWZ0X2pvaW4oYXN0aG1hX2Z1bGwsIGFzdGhtYV8xMywgYnkgPSAiemlwIikgLT4gYXN0aG1hX2Z1bGwKYGBgCgojIyBMb2FkIERhdGEgMjAxMgpsb2FkaW5nIGRhdGEgZm9yIDIwMTIgCmBgYHtyfQphc3RobWFfMTIgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YSIsInJhdyIsICJhc3RobWEiLCAiYXN0aG1hMjAxMi5jc3YiKSkgCmBgYAoKZ2V0dGluZyByaWQgb2YgZW1wdHkgY29scwpgYGB7cn0KYXN0aG1hXzEyICU+JQogIHNsaWNlKDQ6MTAyOSkgLT4gYXN0aG1hXzEyCmBgYAoKY2xlYW5pbmcgZGF0YQpgYGB7cn0KYXN0aG1hXzEyICU+JQogIHNlbGVjdCgtWDMpICU+JQogIHJlbmFtZShjb3VudF8xMiA9IGBNaXNzb3VyaSBFUEhUIEFzdGhtYWApICU+JQogIHJlbmFtZSh6aXAgPSBgVGl0bGU6YCkgLT4gYXN0aG1hXzEyCmBgYAoKY2hhbmdpbmcgWCB0byBOQSBhbmQgY2hhbmdpbmcgY291bnQgdG8gbnVtZXJpYyAKYGBge3J9Cm11dGF0ZShhc3RobWFfMTIsIGNvdW50XzEyID0gaWZlbHNlKGNvdW50XzEyID09ICJ4IiwgTkEsIGNvdW50XzEyKSkgLT4gYXN0aG1hXzEyCmBgYApgYGB7cn0KbXV0YXRlKGFzdGhtYV8xMiwgY291bnRfMTIgPSBhcy5udW1lcmljKGNvdW50XzEyKSkgLT4gYXN0aG1hXzEyCmBgYApsZWZ0IGpvaW5nIHRvIGpvaW5lZF8xM18xNF8xNSBieSB6aXAuIFRhYmxlIG5vdyBoYXMgZGF0YSBmb3IgMjAxMiB0aHJvdWdoIDIwMTUgCmBgYHtyfQpsZWZ0X2pvaW4oYXN0aG1hX2Z1bGwsIGFzdGhtYV8xMiwgYnkgPSAiemlwIikgLT4gYXN0aG1hX2Z1bGwKYGBgCgojIyBMb2FkIERhdGEgMjAxMQpsb2FkaW5nIGRhdGEgZm9yIDIwMTEKYGBge3J9CmFzdGhtYV8xMSA8LSByZWFkX2NzdihoZXJlKCJkYXRhIiwicmF3IiwgImFzdGhtYSIsICJhc3RobWEyMDExLmNzdiIpKSAKYGBgCmdldHRpbmcgcmlkIG9mIGVtcHR5IGNvbHMKYGBge3J9CmFzdGhtYV8xMSAlPiUKICBzbGljZSg0OjEwMjkpIC0+IGFzdGhtYV8xMQpgYGAKCmNsZWFuaW5nIGRhdGEKYGBge3J9CmFzdGhtYV8xMSAlPiUKICBzZWxlY3QoLVgzKSAlPiUKICByZW5hbWUoY291bnRfMTEgPSBgTWlzc291cmkgRVBIVCBBc3RobWFgKSAlPiUKICByZW5hbWUoemlwID0gYFRpdGxlOmApIC0+IGFzdGhtYV8xMQpgYGAKCmNoYW5naW5nIFggdG8gTkEsIGFuZCBjaGFuZ2luZyBjb3VudCB0byBiZSBudW1lcmljIApgYGB7cn0KbXV0YXRlKGFzdGhtYV8xMSwgY291bnRfMTEgPSBpZmVsc2UoY291bnRfMTEgPT0gIngiLCBOQSwgY291bnRfMTEpKSAtPiBhc3RobWFfMTEKYGBgCgpgYGB7cn0KbXV0YXRlKGFzdGhtYV8xMSwgY291bnRfMTEgPSBhcy5udW1lcmljKGNvdW50XzExKSkgLT4gYXN0aG1hXzExCmBgYAoKIyMgSm9pbmluZyBkYXRhIGZvciB5ZWFycyAyMDExLTIwMTUKam9pbmluZyB0byBqb2luZWRfMTJfMTUgZm9yIHllYXJzIDIwMTEtMjAxNQpgYGB7cn0KbGVmdF9qb2luKGFzdGhtYV9mdWxsLCBhc3RobWFfMTEsIGJ5ID0gInppcCIpIC0+IGFzdGhtYV9mdWxsCmBgYAoKam9pbmluZyBkYXRhIHdpdGggZ2VvbWV0cnkgYnkgemlwCmBgYHtyfQphc3RobWFfZnVsbCA8LSBsZWZ0X2pvaW4obW9aaXAsIGFzdGhtYV9mdWxsLCBieSA9ICJ6aXAiKQpgYGAKYGBge3J9CmFzdGhtYV9mdWxsICU+JQpyZW5hbWUoCiAgY291bnRfMTQgPSBjb3VudC55LAogIGNvdW50XzE1ID0gY291bnQueAopIC0+IGFzdGhtYV9mdWxsCmBgYAoKIyMgWmlwIGNvZGVzIGZvciBTdCBMb3VpcyBtZXRybyBhcmVhCgpmaWx0ZXJpbmcgZm9yIFppcCBjb2RlcyBpbiBTdCBMb3VpcyBNZXRybyBBcmVhLCBmaXJzdCBmaWx0ZXIgZ2V0cyByYW5nZSwgRXhjbHVkZSBnZXRzIHJpZCBvZiB6aXAgY29kZXMgaW4gdGhhdCByYW5nZSB0aGF0IGFyZW4ndCBpbmNsdWRlZCBpbiB0aGUgbWV0cm8gYXJlYS4gCmBgYHtyfQphc3RobWFfZnVsbCAlPiUKICBmaWx0ZXIoemlwID49ICg2MzAwNSkpJT4lCiAgZmlsdGVyKHppcCA8PSAoNjMzOTApKSAtPiBhc3RobWFfZnVsbApgYGAKCiAgCmBgYHtyfQpleGNsdWRlIDwtIGMoNjMwOTEsIDYzMTU1LCA2MzMzMywgNjMzMzQsIDYzMzM2LCA2MzMzOSwgNjMzNDQsIDYzMzQ1LCA2MzM1MCwgNjMzNTEsIDYzMzUyLCA2MzM1MywgNjMzNTksIDYzMzU5LCA2MzM2MSwgNjMzNjMsIDYzMzgyLCA2MzM4OCwgNjMzODQsIDYzMDM2LCA2MzA4NywgNjMzMzApCmBgYAoKYGBge3J9CmFzdGhtYV9mdWxsICU+JQpmaWx0ZXIoYXMuY2hhcmFjdGVyKHppcCkgJWluJSBleGNsdWRlID09IEZBTFNFKSAtPiBhc3RobWFfZnVsbApgYGAKCmNoYW5naW5nIE5BJ3MgdG8gMHMKYGBge3J9CmFzdGhtYV9mdWxsJT4lCiAgbXV0YXRlKGNvdW50XzExID0gaWZlbHNlKGlzLm5hKGNvdW50XzExKSA9PSBUUlVFLCAwLCBjb3VudF8xMSkpICU+JQogIG11dGF0ZShjb3VudF8xMiA9IGlmZWxzZShpcy5uYShjb3VudF8xMikgPT0gVFJVRSwgMCwgY291bnRfMTIpKSAlPiUKICBtdXRhdGUoY291bnRfMTMgPSBpZmVsc2UoaXMubmEoY291bnRfMTMpID09IFRSVUUsIDAsIGNvdW50XzEzKSkgJT4lCiAgbXV0YXRlKGNvdW50XzE0ID0gaWZlbHNlKGlzLm5hKGNvdW50XzE0KSA9PSBUUlVFLCAwLCBjb3VudF8xNCkpICU+JQogIG11dGF0ZShjb3VudF8xNSA9IGlmZWxzZShpcy5uYShjb3VudF8xNSkgPT0gVFJVRSwgMCwgY291bnRfMTUpKS0+IGFzdGhtYV9mdWxsCmBgYAoKCiMjIENyZWF0aW5nIENvdW50IHZhcmlhYmxlCkNyZWF0aW5nIGNvdW50IGZvciBhbGwgNSB5ZWFycwoKYGBge3J9CmFzdGhtYV9mdWxsICU+JQogIGdyb3VwX2J5KHppcCkgJT4lCiAgbXV0YXRlKHRvdGFsX2NvdW50ID0gc3VtKGNvdW50XzE1LCBjb3VudF8xNCwgY291bnRfMTMsIGNvdW50XzEyLCBjb3VudF8xMSkpICU+JQogIHNlbGVjdCh6aXAsIHRvdGFsX2NvdW50LCBnZW9tZXRyeSkgLT4gYXN0aG1hX2Z1bGwKYGBgCnJvd3dpc2UoKSAlPiUKZ2V0dGluZyBjZW5zdXMgZGF0YSB0byBnZXQgcG9wdWxhdGlvbiBmb3IgemlwIGNvZGUgdHJhY3RzLiB1c2luZyA1IHllYXIgZXN0aW1hdGVzIGZyb20gMjAxNQpgYGB7cn0KI2FjcyA8LSBsb2FkX3ZhcmlhYmxlcyh5ZWFyID0gMjAxNSwgZGF0YXNldCA9ICJhY3M1IiwgY2FjaGUgPSBUUlVFKQpgYGAKCmBgYHtyfQpwb3AgPC0gZ2V0X2FjcyhnZW9ncmFwaHkgPSAiemlwIGNvZGUgdGFidWxhdGlvbiBhcmVhIiwgeWVhciA9IDIwMTUsIHZhcmlhYmxlcyA9ICJCMDEwMDNfMDAxIiwgc3VydmV5ID0gImFjczUiKQpgYGAKCmZpbHRlcmluZyBmb3IgemlwIGNvZGVzIGluIHN0LiBsb3VpcyBtZXRybyBhcmVhCmBgYHtyfQpwb3AgJT4lCiAgZmlsdGVyKEdFT0lEID49ICg2MzAwNSkpJT4lCiAgZmlsdGVyKEdFT0lEIDw9ICg2MzM5MCkpIC0+cG9wCmBgYApgYGB7cn0KcG9wICU+JQogIGZpbHRlcihhcy5jaGFyYWN0ZXIoR0VPSUQpICVpbiUgZXhjbHVkZSA9PSBGQUxTRSklPiUKICByZW5hbWUoemlwID0gR0VPSUQsCiAgICAgICAgIHBvcCA9IGVzdGltYXRlKSAlPiUKICBzZWxlY3QoemlwLCBwb3ApIC0+IHBvcApgYGAKCmxlZnQgam9pbiBwb3BfbWV0cm8gdG8gYXN0aG1hX2NvdW50X3RvdGFsLCBtYWtpbmcgdmFyaWFibGUgZm9yIGNvdW50IApgYGB7cn0KbGVmdF9qb2luKGFzdGhtYV9mdWxsLCBwb3AsIGJ5ID0gInppcCIpICU+JQogIG11dGF0ZShhc3RobWFfcmF0ZSA9ICh0b3RhbF9jb3VudC9wb3ApKjEwMDApICU+JQogc2VsZWN0KHppcCwgYXN0aG1hX3JhdGUsIGdlb21ldHJ5KSAtPiBhc3RobWFfZnVsbApgYGAKCmBgYHtyfQptYXB2aWV3KGFzdGhtYV9mdWxsKQpgYGAKCmNyZWF0aW5nIGdncGxvdCBtYXAKYGBge3J9CmdncGxvdCgpICsKICAgIGdlb21fc2YoZGF0YSA9IGFzdGhtYV9mdWxsLCBtYXBwaW5nID0gYWVzKGZpbGwgPSBhc3RobWFfcmF0ZSkpICsKICBzY2FsZV9maWxsX2Rpc3RpbGxlcihwYWxldHRlID0gIkdyZWVucyIsIHRyYW5zID0icmV2ZXJzZSIpCmBgYAoKIyMgc2F2aW5nIHNoYXBlZmlsZSBmaWxlIGZvciBBc3RobWEgZGF0YSBmb3IgeWVhcnMgMjAxMS0yMDE1CmBgYHtyfQpkaXIuY3JlYXRlKGhlcmUoImRhdGEiLCJjbGVhbiIsICJhc3RobWEiLCAiYXN0aG1hX2Z1bGwiKSkKc3Rfd3JpdGUoYXN0aG1hX2Z1bGwsIGRzbiA9IGhlcmUoImRhdGEiLCAiY2xlYW4iLCAiYXN0aG1hIiwgImFzdGhtYV9mdWxsIiwgImFzdGhtYV9mdWxsLnNocCIpLCBkZWxldGVfZHNuID0gVFJVRSkKYGBgCgoKIyMgbG9hZGluZyBEYXRhIGZvciAlIEFmcmljYW4gQW1lcmljYW4gCgpsb2FkaW5nIGRhdGEgZm9yIHllYXIgMjAxNSAoZml2ZSB5ZWFyIGVzdGltYXRlKQpgYGB7cn0KYWEgPC0gZ2V0X2FjcyhnZW9ncmFwaHkgPSAiemlwIGNvZGUgdGFidWxhdGlvbiBhcmVhIiwgeWVhciA9IDIwMTUsIHZhcmlhYmxlcyA9ICJCMDIwMDlfMDAxIiwgc3VydmV5ID0gImFjczUiKQpgYGAKCmBgYHtyfQphYSAlPiUKcmVuYW1lKHppcCA9IEdFT0lEKSAtPiBhYQpgYGAKCkpvaW5pbmcgd2l0aCBwb3AgZGF0YQpgYGB7cn0KYWEgPC0gbGVmdF9qb2luKGFhLCBwb3AsIGJ5ID0gInppcCIpIApgYGAKCm5vcm1hbGl6aW5nIGJ5IHBvcApgYGB7cn0KYWEgJT4lCm11dGF0ZShwZXJjZW50X2FhID0gZXN0aW1hdGUvcG9wKSAlPiUKIHJlbmFtZShhZnJpY2FuX2FtZXJpY2FuID0gZXN0aW1hdGUpIC0+IGFhCmBgYAoKam9pbiB3aXRoIGFzdGhtYSBkYXRhIApgYGB7cn0KYWEgPC0gbGVmdF9qb2luKGFzdGhtYV9mdWxsLCBhYSwgYnkgPSAiemlwIikKYGBgCgpgYGB7cn0KYWEgJT4lCiAgc2VsZWN0KHppcCwgYXN0aG1hX3JhdGUsIGFmcmljYW5fYW1lcmljYW4sIHBvcCwgcGVyY2VudF9hYSkgLT4gYWEKYGBgCgpzYXZpbmcgc2hhcGVmaWxlIGZpbGUgZm9yICUgYWZyaWNhbiBhbWVyaWNhbiAKCmBgYHtyfQpkaXIuY3JlYXRlKGhlcmUoImRhdGEiLCJjbGVhbiIsICJkZW1vIiwgInByZWNlbnRfYWEiKSkKc3Rfd3JpdGUoYWEsIGRzbiA9IGhlcmUoImRhdGEiLCAiY2xlYW4iLCAiZGVtbyIsICJwcmVjZW50X2FhIiwgInByZWNlbnRfYWEuc2hwIiksIGRlbGV0ZV9kc24gPSBUUlVFKQpgYGAKCiMjIGxvYWRpbmcgZGF0YSBmb3IgbWVkaWFuIGluY29tZQpsb2FkaW5nIGZpdmUgeWVhciBlc3RpbWF0ZSBmb3IgMjAxNQpgYGB7cn0KbWVkaWFuX2luY29tZSA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ6aXAgY29kZSB0YWJ1bGF0aW9uIGFyZWEiLCB5ZWFyID0gMjAxNSwgdmFyaWFibGVzID0gIkIwNjAxMV8wMDEiLCBzdXJ2ZXkgPSAiYWNzNSIpCmBgYAoKYGBge3J9Cm1lZGlhbl9pbmNvbWUgJT4lCnJlbmFtZSh6aXAgPSBHRU9JRCkgLT4gbWVkaWFuX2luY29tZQpgYGAKCmpvaW4gd2l0aCBwb3AgZGF0YSAKYGBge3J9Cm1lZGlhbl9pbmNvbWUgPC0gbGVmdF9qb2luKG1lZGlhbl9pbmNvbWUsIHBvcCwgYnkgPSAiemlwIikgCgpgYGAKCm5vcm1hbGl6ZSBieSBwb3AKYGBge3J9Cm1lZGlhbl9pbmNvbWUlPiUKbXV0YXRlKGluY29tZV9wcmVjZW50ID0gZXN0aW1hdGUvcG9wKSAlPiUKcmVuYW1lKG1lZGlhbl9pbmNvbWUgPSBlc3RpbWF0ZSkgLT4gbWVkaWFuX2luY29tZQpgYGAKCmpvaW4gd2l0aCBhc3RobWEgZGF0YSAKYGBge3J9Cm1lZGlhbl9pbmNvbWUgPC0gbGVmdF9qb2luKGFzdGhtYV9mdWxsLCBtZWRpYW5faW5jb21lLCBieSA9ICJ6aXAiKQoKYGBgCgoKYGBge3J9Cm1lZGlhbl9pbmNvbWUgJT4lCiAgc2VsZWN0KHppcCwgYXN0aG1hX3JhdGUsIG1lZGlhbl9pbmNvbWUsIHBvcCwgaW5jb21lX3ByZWNlbnQpIC0+IG1lZGlhbl9pbmNvbWUKYGBgCgpzYXZpbmcgYXMgc2hhcGVmaWxlCmBgYHtyfQpkaXIuY3JlYXRlKGhlcmUoImRhdGEiLCJjbGVhbiIsICJkZW1vIiwgIm1lZF9pbmNvbWUiKSkKc3Rfd3JpdGUobWVkaWFuX2luY29tZSwgZHNuID0gaGVyZSgiZGF0YSIsICJjbGVhbiIsICJkZW1vIiwgIm1lZF9pbmNvbWUiLCAibWVkX2luY29tZS5zaHAiKSwgZGVsZXRlX2RzbiA9IFRSVUUpCmBgYAoKIyMgbG9hZGluZyBkYXRhIGZvciBtZWRpYW4gaG9tZSB2YWx1ZSAKCmxvYWRpbmcgNSB5ZWFyIGVzdGltYXRlIGZyb20gMjAxNQpgYGB7cn0KaG9tZV92YWx1ZSA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ6aXAgY29kZSB0YWJ1bGF0aW9uIGFyZWEiLCB5ZWFyID0gMjAxNSwgdmFyaWFibGVzID0gIkIyNTA3N18wMDEiLCBzdXJ2ZXkgPSAiYWNzNSIpCmBgYAoKYGBge3J9CmhvbWVfdmFsdWUgJT4lCnJlbmFtZSh6aXAgPSBHRU9JRCkgLT4gaG9tZV92YWx1ZQpgYGAKCmpvaW5pbmcgd2l0aCBwb3AgZGF0YQpgYGB7cn0KaG9tZV92YWx1ZSA8LSBsZWZ0X2pvaW4oaG9tZV92YWx1ZSwgcG9wLCBieSA9ICJ6aXAiKSAKYGBgCgpub3JtYWxpemluZyBieSBwb3AKYGBge3J9CmhvbWVfdmFsdWUlPiUKbXV0YXRlKHZhbHVlX3BlcmNlbnQgPSBlc3RpbWF0ZS9wb3ApICU+JQpyZW5hbWUoaG9tZV92YWx1ZSA9IGVzdGltYXRlKSAtPiBob21lX3ZhbHVlCmBgYAoKam9pbmluZyB3aXRoIGFzdGhtYSBkYXRhCmBgYHtyfQpob21lX3ZhbHVlIDwtIGxlZnRfam9pbihhc3RobWFfZnVsbCwgaG9tZV92YWx1ZSwgYnkgPSAiemlwIikKYGBgCgoKYGBge3J9CmhvbWVfdmFsdWUgJT4lCiAgc2VsZWN0KHppcCwgYXN0aG1hX3JhdGUsIGhvbWVfdmFsdWUsIHBvcCwgdmFsdWVfcGVyY2VudCkgLT4gaG9tZV92YWx1ZQpgYGAKCnNhdmluZyBhcyBzaGFwZWZpbGUgCmBgYHtyfQpkaXIuY3JlYXRlKGhlcmUoImRhdGEiLCJjbGVhbiIsICJkZW1vIiwgImhvbWVfdmFsdWUiKSkKc3Rfd3JpdGUoaG9tZV92YWx1ZSwgZHNuID0gaGVyZSgiZGF0YSIsICJjbGVhbiIsICJkZW1vIiwgImhvbWVfdmFsdWUiLCAiaG9tZV92YWx1ZS5zaHAiKSwgZGVsZXRlX2RzbiA9IFRSVUUpCmBgYAoKCiMjIGxvYWRpbmcgZGF0YSBmb3IgbWVkaWNhaWRlIApsb2FkaW5nIGZpdmUgeWVhciBlc3RpbWF0ZSBmcm9tIDIwMTUKYGBge3J9Cm1lZGljYWlkIDwtIGdldF9hY3MoZ2VvZ3JhcGh5ID0gInppcCBjb2RlIHRhYnVsYXRpb24gYXJlYSIsIHllYXIgPSAyMDE1LCB2YXJpYWJsZXMgPSAiQjk5MjcwN18wMDEiLCBzdXJ2ZXkgPSAiYWNzNSIpCgpgYGAKCmBgYHtyfQptZWRpY2FpZCAlPiUKcmVuYW1lKHppcCA9IEdFT0lEKSAtPiBtZWRpY2FpZApgYGAKam9pbmluZyB3aXRoIHBvcApgYGB7cn0KbWVkaWNhaWQgPC0gbGVmdF9qb2luKG1lZGljYWlkLCBwb3AsIGJ5ID0gInppcCIpIAoKYGBgCgoKbm9ybWFsaXppbmcgYnkgcG9wCmBgYHtyfQptZWRpY2FpZCAlPiUKbXV0YXRlKHBlcmNlbnRfbWVkaWNhaWQgPSBlc3RpbWF0ZS9wb3ApICU+JQpyZW5hbWUobWVkaWNhaWQgPSBlc3RpbWF0ZSkgLT4gbWVkaWNhaWQKYGBgCmpvaW5pbmcgd2l0aCBhc3RobWEgZGF0YQpgYGB7cn0KbWVkaWNhaWQgPC0gbGVmdF9qb2luKGFzdGhtYV9mdWxsLCBtZWRpY2FpZCwgYnkgPSAiemlwIikKCmBgYAoKCmBgYHtyfQptZWRpY2FpZCAlPiUKICBzZWxlY3QoemlwLCBhc3RobWFfcmF0ZSwgbWVkaWNhaWQsIHBvcCwgcGVyY2VudF9tZWRpY2FpZCkgLT4gbWVkaWNhaWQKYGBgCgpzYXZpbmcgYXMgc2hhcGVmaWxlCmBgYHtyfQpkaXIuY3JlYXRlKGhlcmUoImRhdGEiLCJjbGVhbiIsICJkZW1vIiwgIm1lZGljYWlkIikpCnN0X3dyaXRlKG1lZGljYWlkLCBkc24gPSBoZXJlKCJkYXRhIiwgImNsZWFuIiwgImRlbW8iLCAibWVkaWNhaWQiLCAibWVkaWNhaWQuc2hwIiksIGRlbGV0ZV9kc24gPSBUUlVFKQpgYGAKCiMjIGxvYWRpbmcgZGF0YSBmb3IgJSB1bmRlciBwb3ZlcnR5IGxpbmUKCmxvYWRpbmcgZml2ZSB5ZWFyIGVzdGltYXRlcyBmb3IgMjAxNQpgYGB7cn0KcG92ZXJ0eSA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ6aXAgY29kZSB0YWJ1bGF0aW9uIGFyZWEiLCB5ZWFyID0gMjAxNSwgdmFyaWFibGVzID0gIkIxNzAwMV8wMDIiLCBzdXJ2ZXkgPSAiYWNzNSIpCmBgYApsb2FkaW5nIHBvdmVydHkgdG90YWwKCmBgYHtyfQpwb3ZlcnR5X3RvdGFsIDwtIGdldF9hY3MoZ2VvZ3JhcGh5ID0gInppcCBjb2RlIHRhYnVsYXRpb24gYXJlYSIsIHllYXIgPSAyMDE1LCB2YXJpYWJsZXMgPSAiQjE3MDAxXzAwMSIsIHN1cnZleSA9ICJhY3M1IikKYGBgCgpgYGB7cn0KcG92ZXJ0eSAlPiUKICBzZWxlY3QoR0VPSUQsIGVzdGltYXRlKSAtPiBwb3ZlcnR5CmBgYAoKCmBgYHtyfQpwb3ZlcnR5IDwtIGxlZnRfam9pbihwb3ZlcnR5LCBwb3ZlcnR5X3RvdGFsLCBieSA9ICJHRU9JRCIpIApgYGAKbm9ybWFsaXppbmcgYnkgcG92ZXJ5IHRvdGFsIApgYGB7cn0KcG92ZXJ0eSAlPiUKICBtdXRhdGUocG92ZXJ0eV9wZXJjZW50ID0gZXN0aW1hdGUueC9lc3RpbWF0ZS55KSAlPiUKICByZW5hbWUoemlwID0gR0VPSUQsCiAgICAgICAgIHBvdmVydHkgPSBlc3RpbWF0ZS54LAogICAgICAgICBwb3ZfdG90YWwgPSBlc3RpbWF0ZS55KSAtPiBwb3ZlcnR5CmBgYAoKam9pbmluZyB3aXRoIGFzdGhtYSBkYXRhCmBgYHtyfQpwb3ZlcnR5IDwtIGxlZnRfam9pbihhc3RobWFfZnVsbCwgcG92ZXJ0eSwgYnkgPSAiemlwIikKYGBgCgpgYGB7cn0KcG92ZXJ0eSAlPiUKICBzZWxlY3QoemlwLCBhc3RobWFfcmF0ZSwgcG92ZXJ0eSwgcG92X3RvdGFsLCBwb3ZlcnR5X3BlcmNlbnQpIC0+IHBvdmVydHkKYGBgCgoKCmBgYHtyfQpkaXIuY3JlYXRlKGhlcmUoImRhdGEiLCJjbGVhbiIsICJkZW1vIiwgInBvdmVydHkiKSkKc3Rfd3JpdGUocG92ZXJ0eSwgZHNuID0gaGVyZSgiZGF0YSIsICJjbGVhbiIsICJkZW1vIiwgInBvdmVydHkiLCAicG92ZXJ0eS5zaHAiKSwgZGVsZXRlX2RzbiA9IFRSVUUpCmBgYAoKCg==